package com.wxtech.heartbeat.server;


import java.util.List;

import org.apache.log4j.Logger;


import com.wxtech.heartbeat.server.protocol.DecodeResult;
import com.wxtech.heartbeat.server.protocol.Protocol;
import com.wxtech.heartbeat.server.protocol.ProtocolHelper;
import com.wxtech.heartbeat.util.CHexConver;

import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.ByteToMessageDecoder;

/**
 * 这个类的职责是把数据包封装成HBProtocolData对象，然后后面的Handler进行数据的保存工作。
 */
public class ProtocolDecoder extends ByteToMessageDecoder {
	private static final Logger logger = Logger.getLogger(ProtocolDecoder.class);

	@Override
	protected void decode(ChannelHandlerContext ctx, ByteBuf buffer, List<Object> out) throws Exception {
//		logger.info("starting decoing");
		if (buffer.readableBytes() < Protocol.MIN_BYTE_NUMBER) {
			return;
		}
		logger.debug("get protocol command type");
		String cmdTypeString = ProtocolHelper.getCmdType(buffer);
		logger.debug("received type= 0x" + cmdTypeString);
		if(!ProtocolHelper.isValidCmd(cmdTypeString)) {
			byte[] temp = CHexConver.hexStr2Bytes(cmdTypeString);
			//离开之前dump一份数据
			dump(buffer);
			buffer.skipBytes(temp.length);
 			//假设命令符都是在第一位的，或者前n位的。
 			//不认识这个命令，无效，只好丢弃
 			
 			
 			return;
		}
		Protocol p = ProtocolHelper.getProtocolByCmdHex(cmdTypeString);
		//解析器不应该为null
		if(p == null) {
			throw new RuntimeException("check the code. Protocol should not be null");
		}
		
		logger.debug("begin to decode...");
		//到时候每种数据包都会有一个自己对应的类，去解析
		//生成一个结果
		if(p.isBufferDataEnough(buffer)) {
			DecodeResult dr = p.decode(buffer);
			out.add(dr);
			logger.debug("done");
		} else {
			logger.debug("buffer data is not enough,skip");
		}
		return;
		
	}

//	public ErrorData buildError(ByteBuf buffer, byte[] raw, int errorCode) {
//		buffer.readBytes(raw);
//		ErrorData errorData = new ErrorData();
//		errorData.setErrorCode(errorCode);
//		errorData.setData(raw);
//		return errorData;
//	}

	private void dump(ByteBuf buffer) {
		int b = buffer.readerIndex();
		int len = buffer.readableBytes();
		byte[] data = new byte[len];
		buffer.getBytes(b, data);
		String hex = CHexConver.byte2HexStr(data, len);
		logger.debug("will ignore dump=" + hex);
	}
}
